package com.cms.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cms.entity.Category;
import com.cms.enums.CategoryStatus;
import com.cms.mapper.CategoryMapper;
import com.cms.utils.DbUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 栏目表 服务实现类
 * </p>
 *
 * @author songfayuan
 * @since 2021-11-12
 */
@Service
public class CategoryService extends ServiceImpl<CategoryMapper, Category> {

    /**
     * 根据编码获取分类
     * @return	分类
     */
    public Category findByCode(String code,Integer siteId){
        QueryWrapper<Category> queryWrapper = new QueryWrapper();
        queryWrapper.eq("code",code);
        queryWrapper.eq("siteId",siteId);
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 根据URL目录获取分类
     * @return	分类
     */
    public Category findByCat(String cat,Integer siteId){
        QueryWrapper<Category> queryWrapper = new QueryWrapper();
        queryWrapper.eq("cat",cat);
        queryWrapper.eq("siteId",siteId);
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 根据名称获取分类
     * @return	分类
     */
    public Category findByName(String name,Integer siteId){
        QueryWrapper<Category> queryWrapper = new QueryWrapper();
        queryWrapper.eq("name",name);
        queryWrapper.eq("siteId",siteId);
        return baseMapper.selectOne(queryWrapper);
    }


    /**
     * 检查cat唯一
     *
     * @param cat
     * @param id
     * @return
     */
    public boolean checkCat(String cat,Integer id,Integer siteId){
        if(StringUtils.isBlank(cat)){
            return true;
        }
        if(id!=null){
            Category category = getById(id);
            if(category.getCat().equals(cat)){
                return true;
            }
        }
        Category category = findByCat(cat,siteId);
        return category==null;
    }

    /**
     * 检查code唯一
     *
     * @param code
     * @param id
     * @return
     */
    public boolean checkCode(String code,Integer id,Integer siteId){
        if(StringUtils.isBlank(code)){
            return true;
        }
        if(id!=null){
            Category category = getById(id);
            if(category.getCode().equals(code)){
                return true;
            }
        }
        Category category = findByCode(code,siteId);
        return category==null;
    }

    /**
     * 根据模型ID查询分类
     *
     * @param modelId
     *            模型ID
     * @param siteId
     *            站点ID
     * @return 顶级分类
     */
    public List<Category> findByModelId(Integer modelId,Integer siteId){
        QueryWrapper<Category> queryWrapper = new QueryWrapper();
        if(modelId!=null){
            queryWrapper.eq("modelId",modelId);
        }
        if(siteId!=null){
            queryWrapper.like("siteId",siteId);
        }
        queryWrapper.orderByAsc("grade").orderByDesc("sort");
        List<Category> categorys = baseMapper.selectList(queryWrapper);
        sort(categorys);
        return categorys;
    }

    /**
     * 查找顶级分类
     *
     * @param start
     *            起始位置
     * @param count
     *            数量
     * @return 顶级分类
     */
    public List<Category> findRoots(Integer start,Integer count,Integer siteId){
        QueryWrapper<Category> queryWrapper = new QueryWrapper();
        queryWrapper.isNull("parentId");
        queryWrapper.eq("siteId",siteId).eq("status", CategoryStatus.NORMAL.ordinal());
        queryWrapper.orderByDesc("sort");
        String limit = DbUtils.getCountSql(start,count);
        if(StringUtils.isNotBlank(limit)){
            queryWrapper.last(limit);
        }
        return baseMapper.selectList(queryWrapper);
    }


    /**
     * 查找上级分类
     *
     * @param id
     *            分类Id
     * @param recursive
     *            是否递归
     * @param start
     *            起始位置
     * @param count
     *            数量
     * @return 上级分类
     */
    public List<Category> findParents(Integer id,String code,Boolean recursive,Integer start, Integer count,Integer siteId){
        Category category = null;
        if(id!=null || StringUtils.isNotBlank(code)){
            if(id==null && StringUtils.isNotBlank(code)){
                category = findByCode(code,siteId);
            }else{
                category = getById(id);
            }
        }
        if(category == null || category.getParentId() == null){
            return Collections.emptyList();
        }
        QueryWrapper<Category> queryWrapper = new QueryWrapper();
        queryWrapper.eq("siteId",siteId).eq("status",CategoryStatus.NORMAL.ordinal());
        if(recursive){
            queryWrapper.in("id",category.getParentIds());
            queryWrapper.orderByAsc("grade");
            String limit = DbUtils.getCountSql(start,count);
            if(StringUtils.isNotBlank(limit)){
                queryWrapper.last(limit);
            }
            return baseMapper.selectList(queryWrapper);
        }else{
            queryWrapper.eq("id",category.getParentId());
            return baseMapper.selectList(queryWrapper);
        }
    }


    /**
     * 查找下级分类
     *
     * @param id
     *            栏目Id
     * @param code
     *            编码
     * @param recursive
     *            是否递归
     * @param start
     *            起始位置
     * @param count
     *            数量
     * @return 下级分类
     */
    public List<Category> findChildren(Integer id,String code, Integer status, Boolean recursive, Integer start, Integer count, Integer siteId){
        Category category = null;
        if(id!=null || StringUtils.isNotBlank(code)){
            if(id==null && StringUtils.isNotBlank(code)){
                category = findByCode(code,siteId);
            }else{
                category = getById(id);
            }
        }
        QueryWrapper<Category> queryWrapper = new QueryWrapper();
        queryWrapper.eq("siteId",siteId);
        if(status!=null){
            queryWrapper.eq("status",status);
        }
        if(recursive){
            queryWrapper.orderByAsc("grade").orderByDesc("sort");
            String limit = DbUtils.getCountSql(start,count);
            if(StringUtils.isNotBlank(limit)){
                queryWrapper.last(limit);
            }
            List<Category> categorys;
            if(category!=null){
                queryWrapper.like("treePath",","+category.getId()+",");
                categorys = baseMapper.selectList(queryWrapper);
            }else{
                categorys = baseMapper.selectList(queryWrapper);
            }
            sort(categorys);
            return categorys;
        }else{
            if(category!=null){
                queryWrapper.eq("parentId",category.getId());
            }else{
                queryWrapper.isNull("parentId");
            }
            queryWrapper.orderByDesc("sort");
            return baseMapper.selectList(queryWrapper);
        }
    }

    /**
     * 查找分类树
     *
     * @return 分类树
     */
    public List<Category> findTree(Integer status,Integer siteId){
        return findChildren(null,null,status,true,null,null,siteId);
    }


    /**
     * 排序分类
     *
     * @param categorys
     *            分类
     */
    private void sort(List<Category> categorys) {
        if(categorys == null || categorys.size()==0) {
            return;
        }
        final Map<Integer, Integer> sortMap = new HashMap<Integer, Integer>();
        for (Category category : categorys) {
            sortMap.put(category.getId(), category.getSort());
        }
        Collections.sort(categorys, new Comparator<Category>() {
            @Override
            public int compare(Category category1, Category category2) {
                Integer[] ids1 = (Integer[]) ArrayUtils.add(category1.getParentIds(), category1.getId());
                Integer[] ids2 = (Integer[]) ArrayUtils.add(category2.getParentIds(), category2.getId());
                Iterator<Integer> iterator1 = Arrays.asList(ids1).iterator();
                Iterator<Integer> iterator2 = Arrays.asList(ids2).iterator();
                CompareToBuilder compareToBuilder = new CompareToBuilder();
                while (iterator1.hasNext() && iterator2.hasNext()) {
                    Integer id1 = iterator1.next();
                    Integer id2 = iterator2.next();
                    Integer sort1 = sortMap.get(id1);
                    Integer sort2 = sortMap.get(id2);
                    compareToBuilder.append(sort2,sort1).append(id1, id2);
                    if (!iterator1.hasNext() || !iterator2.hasNext()) {
                        compareToBuilder.append(category1.getGrade(), category2.getGrade());
                    }
                }
                return compareToBuilder.toComparison();
            }
        });
    }

}
